package com.example.managemyself.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.example.managemyself.data.model.User;
import com.example.managemyself.config.AppConfig;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 用户管理工具类，提供用户认证和数据库交互功能
 * 支持本地模式和远程服务器模式
 * 
 * @author ManageMyself Team
 * @version 2.0
 */
public class UserManager {
    private static final String TAG = "UserManager";
    
    // API端点常量
    private static final class ApiEndpoints {
        static final String REGISTER = "/api/users/register";
        static final String LOGIN = "/api/users/login";
        static final String LOGOUT = "/api/logout";
        static final String USER_INFO = "/api/user";
        static final String RESET_PASSWORD = "/api/reset-password";
        static final String VERIFY_CODE = "/api/verify-code";
    }
    
    // SharedPreferences键常量
    private static final class PrefKeys {
        static final String PREF_NAME = "user_prefs";
        static final String USER_ID = "user_id";
        static final String USERNAME = "username";
        static final String EMAIL = "email";
        static final String TOKEN = "token";
        static final String IS_LOGGED_IN = "is_logged_in";
        static final String LOCAL_MODE = "local_mode";
        static final String USER_ROLE = "user_role";
    }
    
    // HTTP相关常量
    private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json");
    private static final int HTTP_TIMEOUT = 30; // 秒
    
    // 线程池和Handler
    private static final ExecutorService executorService = Executors.newCachedThreadPool();
    private static final Handler mainHandler = new Handler(Looper.getMainLooper());
    
    // HTTP客户端
    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(HTTP_TIMEOUT, java.util.concurrent.TimeUnit.SECONDS)
            .readTimeout(HTTP_TIMEOUT, java.util.concurrent.TimeUnit.SECONDS)
            .writeTimeout(HTTP_TIMEOUT, java.util.concurrent.TimeUnit.SECONDS)
            .build();
    
    // 单例实例
    private static volatile UserManager instance;
    
    // 当前登录的用户
    private volatile User currentUser;
    
    // 本地用户数据库（线程安全）
    private static final ConcurrentHashMap<String, User> localUserDatabase = new ConcurrentHashMap<>();
    
    // 配置信息
    private boolean localMode = false; // 默认使用远程模式，连接MySQL数据库
    private String baseUrl;
    
    // 私有构造函数
    private UserManager() {
        // 不再自动初始化本地用户，优先使用远程数据库
    }
    
    /**
     * 获取单例实例（双重检查锁定）
     */
    public static UserManager getInstance() {
        if (instance == null) {
            synchronized (UserManager.class) {
                if (instance == null) {
                    instance = new UserManager();
                }
            }
        }
        return instance;
    }
    
    /**
     * 初始化用户管理器
     */
    public synchronized void init(Context context) {
        try {
            // 强制启用本地模式 - 确保稳定登录
            localMode = true;
            SharedPreferences prefs = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE);
            prefs.edit().putBoolean(PrefKeys.LOCAL_MODE, true).apply();
            Log.i(TAG, "FORCED LOCAL MODE ENABLED for stable login");
            
            // 初始化本地用户数据
            initializeLocalUsers();
            
            // 从配置中获取基础URL（保留用于将来可能的远程模式）
            AppConfig config = AppConfig.getInstance();
            config.init(context);
            baseUrl = config.getApiBaseUrl();
            
            // 检查baseUrl是否为null或空字符串
            if (baseUrl == null || baseUrl.trim().isEmpty()) {
                Log.w(TAG, "API base URL is null or empty, using default value");
                baseUrl = "http://10.163.78.16:8080/api"; // 默认API地址
            }
            
            // 确保baseUrl不以斜杠结尾
            if (baseUrl.endsWith("/")) {
                baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
            }
            
            Log.i(TAG, "UserManager baseUrl initialized: " + baseUrl);
            
            // 检查用户是否已登录
            boolean isLoggedIn = prefs.getBoolean(PrefKeys.IS_LOGGED_IN, false);
            
            if (isLoggedIn) {
                restoreUserSession(prefs);
            }
            
            Log.i(TAG, "UserManager initialized in FORCED LOCAL mode");
            
            // 调试：打印本地用户信息
            debugLocalUsers();
            
        } catch (Exception e) {
            Log.e(TAG, "Error initializing UserManager", e);
            // 确保即使出错也启用本地模式
            localMode = true;
            initializeLocalUsers();
        }
    }
    
    /**
     * 调试：打印本地用户信息
     */
    private void debugLocalUsers() {
        Log.d(TAG, "=== 本地用户数据调试 ===");
        for (String username : localUserDatabase.keySet()) {
            User user = localUserDatabase.get(username);
            if (user != null) {
                Log.d(TAG, "用户: " + username + ", 角色: " + user.getRole() + ", 邮箱: " + user.getEmail());
            }
        }
        Log.d(TAG, "本地用户总数: " + localUserDatabase.size());
        Log.d(TAG, "====================");
    }
    
    /**
     * 测试远程连接
     */
    private void testRemoteConnection() {
        executorService.execute(() -> {
            try {
                Request request = new Request.Builder()
                        .url(baseUrl + "/health")
                        .get()
                        .build();
                
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.w(TAG, "远程服务器连接失败，将在需要时自动切换到本地模式", e);
                    }
                    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if (response.isSuccessful()) {
                            Log.i(TAG, "远程服务器连接成功");
                        } else {
                            Log.w(TAG, "远程服务器响应异常: " + response.code());
                        }
                    }
                });
            } catch (Exception e) {
                Log.w(TAG, "测试远程连接时发生错误", e);
            }
        });
    }
    
    /**
     * 启用本地模式作为备用方案
     */
    private void enableLocalModeAsFallback(Context context) {
        localMode = true;
        initializeLocalUsers();
        
        // 保存本地模式设置
        SharedPreferences prefs = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE);
        prefs.edit().putBoolean(PrefKeys.LOCAL_MODE, true).apply();
        
        Log.w(TAG, "已启用本地模式作为备用方案");
    }
    
    /**
     * 恢复用户会话
     */
    private void restoreUserSession(SharedPreferences prefs) {
        try {
            int userId = prefs.getInt(PrefKeys.USER_ID, -1);
            String username = prefs.getString(PrefKeys.USERNAME, "");
            String email = prefs.getString(PrefKeys.EMAIL, "");
            String role = prefs.getString(PrefKeys.USER_ROLE, User.ROLE_USER);
            
            if (userId != -1 && !username.isEmpty()) {
                currentUser = new User();
                currentUser.setId(userId);
                currentUser.setUsername(username);
                currentUser.setEmail(email);
                currentUser.setRole(role);
                
                Log.i(TAG, "User session restored: " + username + " (" + role + ")");
            }
        } catch (Exception e) {
            Log.e(TAG, "Error restoring user session", e);
            currentUser = null;
        }
    }
    
    /**
     * 初始化本地用户数据
     */
    private void initializeLocalUsers() {
        // 创建默认管理员用户
        User admin = new User();
        admin.setId(1);
        admin.setUsername("admin");
        admin.setEmail("admin@managemyself.com");
        admin.setPassword("admin123"); // 在实际应用中应该加密
        admin.setRole(User.ROLE_ADMIN);
        localUserDatabase.put("admin", admin);
        
        // 创建默认普通用户
        User user = new User();
        user.setId(2);
        user.setUsername("user");
        user.setEmail("user@managemyself.com");
        user.setPassword("user123"); // 在实际应用中应该加密
        user.setRole(User.ROLE_USER);
        localUserDatabase.put("user", user);
        
        Log.d(TAG, "Local users initialized");
    }
    
    /**
     * 设置本地模式
     */
    public synchronized void setLocalMode(Context context, boolean localMode) {
        this.localMode = localMode;
        SharedPreferences prefs = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE);
        prefs.edit().putBoolean(PrefKeys.LOCAL_MODE, localMode).apply();
        Log.i(TAG, "Local mode set to: " + localMode);
    }
    
    /**
     * 是否为本地模式
     */
    public boolean isLocalMode() {
        return localMode;
    }
    
    // 回调接口定义
    public interface AuthCallback {
        void onSuccess(User user);
        void onError(String error);
    }
    
    public interface SimpleCallback {
        void onSuccess();
        void onError(String error);
    }
    
    /**
     * 用户注册
     */
    public void register(Context context, String username, String password, String email, AuthCallback callback) {
        if (localMode) {
            registerLocalUser(context, username, email, password, callback);
            return;
        }
        
        // 检查baseUrl是否有效
        if (baseUrl == null || baseUrl.trim().isEmpty()) {
            Log.w(TAG, "Base URL is null, switching to local mode");
            registerLocalUser(context, username, email, password, callback);
            return;
        }
        
        executorService.execute(() -> {
            try {
                JSONObject requestBody = new JSONObject();
                requestBody.put("username", username);
                requestBody.put("password", password);
                requestBody.put("email", email);
                
                String registerUrl = baseUrl + ApiEndpoints.REGISTER;
                Log.d(TAG, "Register URL: " + registerUrl);
                
                Request request = new Request.Builder()
                        .url(registerUrl)
                        .post(RequestBody.create(JSON_MEDIA_TYPE, requestBody.toString()))
                        .addHeader("Content-Type", "application/json")
                        .build();
                
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.w(TAG, "Remote register failed, trying local", e);
                        registerLocalUser(context, username, email, password, callback);
                    }
                    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        handleRegisterResponse(context, response, username, email, callback);
                    }
                });
            } catch (Exception e) {
                Log.e(TAG, "Error in register", e);
                mainHandler.post(() -> callback.onError("注册失败: " + e.getMessage()));
            }
        });
    }
    
    /**
     * 处理注册响应
     */
    private void handleRegisterResponse(Context context, Response response, String username, String email, AuthCallback callback) {
        try {
            String responseBody = response.body() != null ? response.body().string() : "";
            
            // 添加详细的调试日志
            Log.d(TAG, "Register response status: " + response.code());
            Log.d(TAG, "Register response body length: " + responseBody.length());
            Log.d(TAG, "Register response body: " + responseBody);
            
            // 检查响应体是否为空
            if (responseBody.isEmpty()) {
                Log.e(TAG, "Server returned empty response body");
                mainHandler.post(() -> callback.onError("服务器返回空响应，请检查服务器状态"));
                return;
            }
            
            // 检查响应是否为HTML错误页面
            if (responseBody.trim().startsWith("<")) {
                Log.e(TAG, "Server returned HTML instead of JSON: " + responseBody.substring(0, Math.min(200, responseBody.length())));
                mainHandler.post(() -> callback.onError("服务器返回HTML页面而非JSON数据，请检查API地址配置"));
                return;
            }
            
            JSONObject jsonResponse = new JSONObject(responseBody);
            
            if (response.isSuccessful()) {
                int userId = jsonResponse.getInt("id");
                String token = jsonResponse.optString("token", "");
                
                User user = new User();
                user.setId(userId);
                user.setUsername(username);
                user.setEmail(email);
                user.setRole(User.ROLE_USER);
                
                saveUserData(context, user, token);
                currentUser = user;
                
                mainHandler.post(() -> callback.onSuccess(user));
            } else {
                String error = jsonResponse.optString("error", "注册失败");
                Log.w(TAG, "Register failed with error: " + error);
                mainHandler.post(() -> callback.onError(error));
            }
        } catch (JSONException e) {
            Log.e(TAG, "JSON parsing error in register response", e);
            mainHandler.post(() -> callback.onError("服务器响应格式错误，请检查服务器配置"));
        } catch (IOException e) {
            Log.e(TAG, "IO error reading register response", e);
            mainHandler.post(() -> callback.onError("读取服务器响应失败: " + e.getMessage()));
        } catch (Exception e) {
            Log.e(TAG, "Unexpected error handling register response", e);
            mainHandler.post(() -> callback.onError("处理注册响应时发生未知错误: " + e.getMessage()));
        }
    }
    
    /**
     * 本地用户注册
     */
    private void registerLocalUser(Context context, String username, String email, String password, AuthCallback callback) {
        executorService.execute(() -> {
            try {
                // 检查用户名是否已存在
                if (localUserDatabase.containsKey(username)) {
                    mainHandler.post(() -> callback.onError("用户名已存在"));
                    return;
                }
                
                // 创建新用户
                User user = new User();
                user.setId(localUserDatabase.size() + 1);
                user.setUsername(username);
                user.setEmail(email);
                user.setPassword(password); // 实际应用中应该加密
                user.setRole(User.ROLE_USER);
                
                // 保存到本地数据库
                localUserDatabase.put(username, user);
                
                // 保存用户数据
                saveUserData(context, user, "local_token");
                currentUser = user;
                
                Log.i(TAG, "Local user registered: " + username);
                mainHandler.post(() -> callback.onSuccess(user));
                
            } catch (Exception e) {
                Log.e(TAG, "Error in local register", e);
                mainHandler.post(() -> callback.onError("本地注册失败: " + e.getMessage()));
            }
        });
    }
    
    /**
     * 用户登录
     */
    public void login(Context context, String username, String password, AuthCallback callback) {
        if (localMode) {
            loginLocalUser(context, username, password, callback);
            return;
        }
        
        // 检查baseUrl是否有效
        if (baseUrl == null || baseUrl.trim().isEmpty()) {
            Log.w(TAG, "Base URL is null, switching to local mode");
            loginLocalUser(context, username, password, callback);
            return;
        }
        
        executorService.execute(() -> {
            try {
                JSONObject requestBody = new JSONObject();
                requestBody.put("username", username);
                requestBody.put("password", password);
                
                String loginUrl = baseUrl + ApiEndpoints.LOGIN;
                Log.d(TAG, "Login URL: " + loginUrl);
                
                Request request = new Request.Builder()
                        .url(loginUrl)
                        .post(RequestBody.create(JSON_MEDIA_TYPE, requestBody.toString()))
                        .addHeader("Content-Type", "application/json")
                        .build();
                
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.w(TAG, "Remote login failed, trying local", e);
                        loginLocalUser(context, username, password, callback);
                    }
                    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        handleLoginResponse(context, response, callback);
                    }
                });
            } catch (Exception e) {
                Log.e(TAG, "Error in login", e);
                mainHandler.post(() -> callback.onError("登录失败: " + e.getMessage()));
            }
        });
    }
    
    /**
     * 处理登录响应
     */
    private void handleLoginResponse(Context context, Response response, AuthCallback callback) {
        try {
            String responseBody = response.body() != null ? response.body().string() : "";
            
            // 添加详细的调试日志
            Log.d(TAG, "Login response status: " + response.code());
            Log.d(TAG, "Login response body length: " + responseBody.length());
            Log.d(TAG, "Login response body: " + responseBody);
            
            // 检查响应体是否为空
            if (responseBody.isEmpty()) {
                Log.e(TAG, "Server returned empty response body");
                mainHandler.post(() -> callback.onError("服务器返回空响应，请检查服务器状态"));
                return;
            }
            
            // 检查响应是否为HTML错误页面
            if (responseBody.trim().startsWith("<")) {
                Log.e(TAG, "Server returned HTML instead of JSON: " + responseBody.substring(0, Math.min(200, responseBody.length())));
                mainHandler.post(() -> callback.onError("服务器返回HTML页面而非JSON数据，请检查API地址配置"));
                return;
            }
            
            JSONObject jsonResponse = new JSONObject(responseBody);
            
            if (response.isSuccessful()) {
                User user = parseUserFromJson(jsonResponse);
                String token = jsonResponse.optString("token", "");
                
                saveUserData(context, user, token);
                currentUser = user;
                
                Log.i(TAG, "Remote login successful: " + user.getUsername());
                mainHandler.post(() -> callback.onSuccess(user));
            } else {
                String error = jsonResponse.optString("error", "登录失败");
                Log.w(TAG, "Login failed with error: " + error);
                mainHandler.post(() -> callback.onError(error));
            }
        } catch (JSONException e) {
            Log.e(TAG, "JSON parsing error in login response", e);
            mainHandler.post(() -> callback.onError("服务器响应格式错误，请检查服务器配置"));
        } catch (IOException e) {
            Log.e(TAG, "IO error reading login response", e);
            mainHandler.post(() -> callback.onError("读取服务器响应失败: " + e.getMessage()));
        } catch (Exception e) {
            Log.e(TAG, "Unexpected error handling login response", e);
            mainHandler.post(() -> callback.onError("处理登录响应时发生未知错误: " + e.getMessage()));
        }
    }
    
    /**
     * 从JSON解析用户对象
     */
    private User parseUserFromJson(JSONObject json) throws JSONException {
        User user = new User();
        user.setId(json.getInt("id"));
        user.setUsername(json.getString("username"));
        user.setEmail(json.optString("email", ""));
        
        String roleStr = json.optString("role", "USER");
        if ("ADMIN".equalsIgnoreCase(roleStr)) {
            user.setRole(User.ROLE_ADMIN);
        } else {
            user.setRole(User.ROLE_USER);
        }
        
        return user;
    }
    
    /**
     * 本地用户登录
     */
    private void loginLocalUser(Context context, String username, String password, AuthCallback callback) {
        executorService.execute(() -> {
            try {
                User user = localUserDatabase.get(username);
                if (user == null) {
                    mainHandler.post(() -> callback.onError("用户不存在"));
                    return;
                }
                
                if (!password.equals(user.getPassword())) {
                    mainHandler.post(() -> callback.onError("密码错误"));
                    return;
                }
                
                saveUserData(context, user, "local_token");
                currentUser = user;
                
                Log.i(TAG, "Local login successful: " + username);
                mainHandler.post(() -> callback.onSuccess(user));
                
            } catch (Exception e) {
                Log.e(TAG, "Error in local login", e);
                mainHandler.post(() -> callback.onError("本地登录失败: " + e.getMessage()));
            }
        });
    }
    
    /**
     * 用户登出
     */
    public void logout(Context context, SimpleCallback callback) {
        executorService.execute(() -> {
            try {
                clearUserData(context);
                currentUser = null;
                
                Log.i(TAG, "User logged out");
                mainHandler.post(callback::onSuccess);
                
            } catch (Exception e) {
                Log.e(TAG, "Error in logout", e);
                mainHandler.post(() -> callback.onError("登出失败: " + e.getMessage()));
            }
        });
    }
    
    /**
     * 保存用户数据到SharedPreferences
     */
    private void saveUserData(Context context, User user, String token) {
        SharedPreferences prefs = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE);
        prefs.edit()
                .putInt(PrefKeys.USER_ID, user.getId())
                .putString(PrefKeys.USERNAME, user.getUsername())
                .putString(PrefKeys.EMAIL, user.getEmail())
                .putString(PrefKeys.TOKEN, token)
                .putString(PrefKeys.USER_ROLE, user.getRole())
                .putBoolean(PrefKeys.IS_LOGGED_IN, true)
                .apply();
    }
    
    /**
     * 清除用户数据
     */
    private void clearUserData(Context context) {
        SharedPreferences prefs = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE);
        prefs.edit()
                .remove(PrefKeys.USER_ID)
                .remove(PrefKeys.USERNAME)
                .remove(PrefKeys.EMAIL)
                .remove(PrefKeys.TOKEN)
                .remove(PrefKeys.USER_ROLE)
                .putBoolean(PrefKeys.IS_LOGGED_IN, false)
                .apply();
    }
    
    /**
     * 获取当前登录的用户
     */
    public User getCurrentUser() {
        return currentUser;
    }
    
    /**
     * 更新当前用户信息
     */
    public void updateCurrentUser(User user) {
        if (user != null && currentUser != null && user.getId() == currentUser.getId()) {
            this.currentUser = user;
            // 如果是本地模式，也更新本地数据库
            if (localMode) {
                localUserDatabase.put(user.getUsername(), user);
            }
            Log.i(TAG, "Current user updated: " + user.getUsername());
        }
    }
    
    /**
     * 检查是否已登录
     */
    public boolean isLoggedIn() {
        return currentUser != null;
    }
    
    /**
     * 获取用户Token
     */
    public String getToken(Context context) {
        SharedPreferences prefs = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE);
        return prefs.getString(PrefKeys.TOKEN, "");
    }
    
    /**
     * 检查当前用户是否为管理员
     */
    public boolean isCurrentUserAdmin() {
        return currentUser != null && User.ROLE_ADMIN.equals(currentUser.getRole());
    }
    
    /**
     * 检查当前用户是否为普通用户
     */
    public boolean isCurrentUserUser() {
        return currentUser != null && User.ROLE_USER.equals(currentUser.getRole());
    }
    
    /**
     * 创建默认管理员（如果需要）
     */
    public void createDefaultAdminIfNeeded(Context context) {
        if (localMode && !localUserDatabase.containsKey("admin")) {
            initializeLocalUsers();
            Log.i(TAG, "Default admin created");
        }
    }
    
    /**
     * 获取本地用户数据库（用于测试）
     */
    public ConcurrentHashMap<String, User> getLocalUserDatabase() {
        return localUserDatabase;
    }
    
    /**
     * 清理资源
     */
    public static void cleanup() {
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
        }
    }
    
    /**
     * 安全地构建API URL
     * @param endpoint API端点
     * @return 完整的API URL
     */
    private String buildApiUrl(String endpoint) {
        // 检查baseUrl是否有效
        if (baseUrl == null || baseUrl.trim().isEmpty()) {
            Log.w(TAG, "Base URL is null, using default");
            baseUrl = "http://10.163.78.16:8080/api";
        }
        
        // 确保baseUrl不以斜杠结尾
        String cleanBaseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
        
        // 确保endpoint以斜杠开头
        String cleanEndpoint = (endpoint != null && !endpoint.startsWith("/")) ? "/" + endpoint : endpoint;
        
        String fullUrl = cleanBaseUrl + (cleanEndpoint != null ? cleanEndpoint : "");
        Log.d(TAG, "Built API URL: " + fullUrl);
        return fullUrl;
    }
} 